package com.meatball.game.service.impl

//import org.springframework.cloud.context.config.annotation.RefreshScope
import com.alibaba.fastjson.JSON
import com.meatball.game.asr.AsrClient
import com.meatball.game.asr.AsrResponse
import com.meatball.game.data.*
import com.meatball.game.data.entity.ChatHistory
import com.meatball.game.repository.ChatHistoryRepository
import com.meatball.game.service.AiGameService
import com.meatball.game.service.RoomCacheService
import com.meatball.game.util.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.socket.TextMessage
import java.util.concurrent.TimeUnit

/**
 * TODO 游戏基础信息接口实现层
 *
 * @author 张翔宇
 * @since 2024年3月7日
 */
@Service
//@RefreshScope
class AiGameServiceImpl(
        private val stringRedisTemplate: StringRedisTemplate,
        private val chatHistoryRepository: ChatHistoryRepository,
        private val asrComponent: AsrComponent,
        private val roomCacheService: RoomCacheService
): AiGameService {
    companion object {
        private val logger = LoggerFactory.getLogger(AiGameServiceImpl::class.java)
    }
    @Value("\${chat.host}")
    lateinit var chatHost: String

    val client = OkHttpClient().newBuilder()
            .connectTimeout(10, TimeUnit.SECONDS)  // 设置连接超时
            .readTimeout(30, TimeUnit.SECONDS)     // 设置读取超时
            .writeTimeout(15, TimeUnit.SECONDS)    // 设置写入超时
            .build()
    override fun randomUser(): RandomUser {
        return generatorRandomUser()
    }

    override fun startGame(data: StartGame): List<Player> {
        val result = JSON.parseObject(doRequest(JSON.toJSONString(data), "/v1/games"), StartGameResponse::class.java)
        logger.info("开始游戏返回结果：$result")
        if (result.code == 200) {
            // 设置倒计时后提醒
//            stringRedisTemplate.opsForValue().set("${COUNTDOWN}:${data.id}:5", "", 5, TimeUnit.SECONDS)
//            stringRedisTemplate.opsForValue().set("${COUNTDOWN}:${data.id}:10", "", 10, TimeUnit.SECONDS)
            stringRedisTemplate.opsForValue().set(COUNTDOWN + data.id, "", getRandomNumberInRange(5, 10), TimeUnit.SECONDS)
            val time: Long = when (data.gameType) {
                "find_ai_2" -> 60L
                "find_ai_3" -> 90L
                "find_ai_4" -> 120L
                else -> 0L
            }
            if (time > 0) {
                stringRedisTemplate.opsForValue().set(HALF_TIME + data.id, "", time, TimeUnit.SECONDS)
            }
            return result.results.players
        }
        return mutableListOf()
    }

    override fun chat(data: ChatParams, room: Room) {
        chatHistoryRepository.save(ChatHistory(
                roomId = room.id,
                text = JSON.toJSONString(data)
        ))
        val result = JSON.parseObject(doRequest(JSON.toJSONString(data), "/v1/games/${room.id}"), ChatResponse::class.java)
        logger.info("聊天返回信息：$result")
        // 找出ai用户，组装发送参数
        if (result.code == 200) {
            result.results.forEachIndexed { index, chat ->
//                if (index > 0) {
//                    Thread.sleep(chat.content.length * 1000L)
//                }
                if (chat.content == "no_reply") return@forEachIndexed
                Thread.sleep(chat.content.length * 1000L)
                val user = room.users.first { it.id == chat.playerId }
                room.users.filter { !it.isAi }.forEach {
                    it.session?.sendMessage(TextMessage(JSON.toJSONString(ChatMessage(
                        id = chat.playerId,
                        from = user.name,
                        avatar = user.avatar,
                        text = chat.content
                ))))
                }
            }
        }
        chatHistoryRepository.save(ChatHistory(
                roomId = room.id,
                text = JSON.toJSONString(result.results)
        ))
    }

    override fun castingVote(gameId: String, data: CastingVote) : CastingVoteResult {
        val result = JSON.parseObject(doRequest(JSON.toJSONString(data), "/v1/games/$gameId/vote"), CastingVoteResponse::class.java)
        if (result.code == 200) {
            return result.results
        }
        throw IllegalArgumentException("请求错误")
    }

    override fun getUsers(roomId: String): List<RoomUser>? {
        logger.info("查询用户信息：$roomId")
        val users = JSON.parseArray(stringRedisTemplate.opsForValue().get(ROOM + roomId), RoomUser::class.java)
        return users
//        return roomCacheService.getRoom(roomId)?.users
    }

    override fun getVoteResult(roomId: String): GetVoteResult {
        val request = Request.Builder()
                .url("$chatHost/v1/games/$roomId/vote")
                .build()
        val result = JSON.parseObject(client.newCall(request).execute().body.string(), GetVoteResultResponse::class.java)
        if (result.code == 200) {
            // 删除redis中房间缓存信息
            stringRedisTemplate.delete(ROOM + roomId)
            return result.results
        }
        throw IllegalArgumentException("请求出错")
    }

    override fun expirationKey(key: String) {
        val keys = key.split(":")
        val room = roomCacheService.getRoom(keys[1]) ?: return
        if (room.isRealUser) return
        // 找出AI的用户
        val ai = room.users.first { it.isAi }
        // 发送的文本
        val text = GLOBAL_ARRAY_5.random()
        room.users.filter { !it.isAi && it.session?.isOpen ?: false }.forEach {
            it.session?.sendMessage(TextMessage(JSON.toJSONString(ChatMessage(
                    id = ai.id,
                    from = ai.name,
                    avatar = ai.avatar,
                    text = text
            ))))
        }
    }

    override fun halfTime(key: String) {
        logger.info("中场结论：$key")
        val keys = key.split(":")
        val room = roomCacheService.getRoom(keys[1]) ?: return
        if (room.isRealUser) return
        // 找出AI的用户
        val ai = room.users.first { it.isAi }
        // 发送信息给chat端
        val chat = ChatParams(
                playerId = ai.id,
                content = "summary_47E5"
        )
        chat(chat, room)
    }

    override fun testRedis() {
        stringRedisTemplate.opsForValue().set("xiaomingzaigansha", "123123", 5, TimeUnit.SECONDS)
    }

    override fun handleFileUpload(file: MultipartFile) {
        asrComponent.voiceToText(file.bytes)
    }

    /*override fun handleFileUpload(file: MultipartFile) {
        val asrClient = AsrClient.build()
        asrClient.setAppid("8539369939")
        asrClient.setToken("-OJU8flRWI9tg9sUxRRdGoEtruf5PaVL")
        asrClient.setCluster("volcengine_input_common")
        asrClient.setFormat("wav")
        asrClient.setShowUtterances(true)
        asrClient.asrSyncConnect()
        try {
            var asrResponse = AsrResponse()
            val b = ByteArray(16000)
            var len: Int
            var count = 0
            file.inputStream.use { inputStream ->
                while (inputStream.read(b).also { len = it } > 0) {
                    count += 1
                    logger.info("发送数据包长度: {}, 计数 {}, 是否为最后一个 {}", len, count, inputStream.available() == 0)
                    asrResponse = asrClient.asrSend(b.copyOfRange(0, len), inputStream.available() == 0)
                }
            }
            for (result in asrResponse.result!!) {
                logger.info(result.text)
            }
        } catch (e: Exception) {
            logger.error("asr error", e)
        } finally {
            asrClient.asrClose()
        }
    }*/

    private fun doRequest(data: String, path: String) : String {
        // 创建RequestBody，并设置MediaType为JSON
        val requestBody = data.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())

        val request = Request.Builder()
                .url(chatHost + path)
                .post(requestBody)
                .build()

        client.newCall(request).execute().use {
            if (!it.isSuccessful) throw IllegalArgumentException("Unexpected code $it")
            val responseBody = it.body.string()
            logger.info("开始游戏返回：$responseBody")
            return responseBody
        }
    }
}